package redis.inaction.ratelimiter.configuration;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.cloud.gateway.config.GatewayAutoConfiguration;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.cloud.gateway.support.ConfigurationService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import reactor.core.publisher.Mono;
import redis.inaction.ratelimiter.filter.ratelimit.ApiKeyResolver;
import redis.inaction.ratelimiter.filter.ratelimit.ApiRateLimiterGatewayFilterFactory;
import redis.inaction.ratelimiter.filter.ratelimit.ApiRedisRateLimiter;

import java.util.List;

@Configuration
@AutoConfigureAfter(GatewayAutoConfiguration.class)
public class RateLimiterAutoConfiguration {

    @Bean( value = "pathKeyResolver")
    @Primary
    public KeyResolver pathKeyResolver(){
        return exchange -> Mono.just(exchange.getRequest().getPath().toString());
    }

    @Bean
    public ApiKeyResolver apiKeyResolver(){
        return new ApiKeyResolver();
    }

    @Primary
    @Bean( value = "apiRedisRateLimiter" )
    public ApiRedisRateLimiter apiRedisRateLimiter(ReactiveStringRedisTemplate redisTemplate,
                                                   @Qualifier(RedisRateLimiter.REDIS_SCRIPT_NAME)
                                                   RedisScript<List<Long>> redisScript,
                                                   ConfigurationService configurationService) {
        return new ApiRedisRateLimiter(redisTemplate, redisScript, configurationService);
    }

    @Bean
    public ApiRateLimiterGatewayFilterFactory apiRateLimiterGatewayFilterFactory(ApiRedisRateLimiter rateLimiter,
                                                                                 ApiKeyResolver resolver) {
        return new ApiRateLimiterGatewayFilterFactory(rateLimiter, resolver);
    }

}
